﻿'''
Created on 2011-4-16

@author: Bob
'''
########################_#######################_#######################
#
#排序类型
from random import choice, shuffle
from copy import copy
ST_ORDER                = 0                     #大小排序
ST_COUNT                = 1                     #数目排序

#数目定义
MAX_COUNT               = 20                    #最大数目
FULL_COUNT              = 54                    #全牌数目
GOOD_CARD_COUTN         = 38                    #好牌数目
BACK_COUNT              = 3                     #底牌数目
NORMAL_COUNT            = 17                    #常规数目
 
#数值掩码
MASK_COLOR              = 0xF0                  #花色掩码
MASK_VALUE              = 0x0F                  #数值掩码

#扑克类型
CT_ERROR                = 0                     #错误类型
CT_SINGLE               = 1                     #单牌类型
CT_DOUBLE               = 2                     #对牌类型
CT_THREE                = 3                     #三条类型
CT_SINGLE_LINE          = 4                     #单连类型
CT_DOUBLE_LINE          = 5                     #对连类型
CT_THREE_LINE           = 6                     #三连类型
CT_THREE_LINE_TAKE_ONE  = 7                     #三带一单
CT_THREE_LINE_TAKE_TWO  = 8                     #三带一对
CT_FOUR_LINE_TAKE_ONE   = 9                     #四带两单
CT_FOUR_LINE_TAKE_TWO   = 10                    #四带两对
CT_BOMB_CARD            = 11                    #炸弹类型
CT_MISSILE_CARD         = 12                    #火箭类型

FullCardData = [    
    0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,    #方块 A - K
    0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,    #梅花 A - K
    0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,    #红桃 A - K
    0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,    #黑桃 A - K
    0x4E,0x4F ]

GoodCardData = [
0x01,0x02,
0x11,0x12,
0x21,0x22,
0x31,0x32,
0x4E,0x4F,
0x07,0x08,0x09,
0x17,0x18,0x19,
0x27,0x28,0x29,
0x37,0x38,0x39,
0x0A,0x0B,0x0C,0x0D,
0x1A,0x1B,0x1C,0x1D,
0x2A,0x2B,0x2C,0x2D,
0x3A,0x3B,0x3C,0x3D]

#分析结构
class AnalyseResult:
    Success             = False
    FourCount           = 0                     #四张数目
    ThreeCount          = 0                     #三张数目
    DoubleCount         = 0                     #两张数目
    SignedCount         = 0                     #单张数目
    FourCardData        = []                    #四张扑克
    ThreeCardData       = []                    #三张扑克
    DoubleCardData      = []                    #两张扑克
    SignedCardData      = []                    #单张扑克
    
class OutCardResult:
    CardCount           = 0                     #扑克数目
    ResultCard          = []                    #结果扑克
         
class OutCardTypeResult:
    CardType            = 0                     #扑克类型
    CardTypeCount       = 0                     #牌型数目
    EachHandCardCount   = []                    #每手个数
    CardData            = []                    #扑克数据

#扑克信息    
class HandCardInfo:
    HandCardData        = []                    #扑克数据
    HandCardCount       = []                    #扑克数目
    CardTypeResult      = []                    #分析数据                        
    
class GameLogic:
    #变量定义
    CardData            = []                    #扑克数据
    GoodcardData        = []                    #好牌数据
    
    #AI变量
    AllCardData         = []                    #所有扑克
    LandScoreCardData   = []                    #叫牌扑克
    UserCardCount       = []                    #扑克数目
    BankerUser          = 0                     #地主玩家
    BankerOutCardCount  = 0                     #出牌次数

    def __init__(self):
        #AI变量
        self.BankerOutCardCount = 0
    
    ######### 类型函数
    #获取类型                              
    def GetCardType(self, CardData):
        cardCount = len(CardData)
        if(cardCount == 0):     #空牌
            return CT_ERROR
        elif(cardCount == 1):   #单牌
            return CT_SINGLE
        elif(cardCount == 2):   #对牌火箭
            if(CardData[0] == 0x4F and CardData[1] == 0x4E):
                return CT_MISSILE_CARD
            if(self.GetCardLogicValue(CardData[0]) == self.GetCardLogicValue(CardData[1])):
                return CT_DOUBLE
        
        analyseResult = AnalyseResult()
        if(not analyseResult.Success):
            return CT_ERROR
        
        #analyseResult = self.AnalysebCardData(CardData)
        #四牌判断
        if(analyseResult.FourCount > 0):
            if ((analyseResult.FourCount==1) and (cardCount==4)):
                return CT_BOMB_CARD
        if ((analyseResult.FourCount==1) and (analyseResult.SignedCount==2) and (cardCount==6)):
            return CT_FOUR_LINE_TAKE_ONE
        if ((analyseResult.FourCount==1) and (analyseResult.DoubleCount==2) and (cardCount==8)):
            return CT_FOUR_LINE_TAKE_TWO
        
        #三牌判断
        if (analyseResult.ThreeCount>0):
            #三条类型
            if(analyseResult.ThreeCount==1 and cardCount==3):
                return CT_THREE

            #连牌判断
            if (analyseResult.ThreeCount>1):
                #变量定义
                cardData = analyseResult.ThreeCardData[0]
                firstLogicValue = self.GetCardLogicValue(cardData)
    
                #错误过虑
                if (firstLogicValue>=15):
                    return CT_ERROR
    
                #连牌判断
                for i in range(analyseResult.ThreeCount):
                    cardData = analyseResult.ThreeCardData[i*3]
                    if (firstLogicValue!=(self.GetCardLogicValue(cardData)+i)):
                        return CT_ERROR
            #牌形判断
            if (analyseResult.ThreeCount*3==cardCount):
                return CT_THREE_LINE
            if (analyseResult.ThreeCount*4==cardCount):
                return CT_THREE_LINE_TAKE_ONE
            if ((analyseResult.ThreeCount*5==cardCount)and(analyseResult.DoubleCount==analyseResult.ThreeCount)):
                return CT_THREE_LINE_TAKE_TWO
    
            return CT_ERROR
        
        #两张类型
        if (analyseResult.DoubleCount>=3):
            #变量定义
            cardData = analyseResult.DoubleCardData[0]
            firstLogicValue = self.GetCardLogicValue(CardData)

            #错误过虑
            if (firstLogicValue>=15):
                return CT_ERROR
    
            #连牌判断
            for i in range(analyseResult.DoubleCount):
                cardData=analyseResult.DoubleCardData[i*2]
                if (firstLogicValue!=(self.GetCardLogicValue(CardData)+i)):
                    return CT_ERROR
    
            #二连判断
            if ((analyseResult.DoubleCount*2)==cardCount):
                return CT_DOUBLE_LINE
    
            return CT_ERROR

        #单张判断
        if ((analyseResult.SignedCount>=5)and(analyseResult.SignedCount==cardCount)):
            #变量定义
            cardData = analyseResult.SignedCardData[0]
            firstLogicValue = self.GetCardLogicValue(cardData)
    
            #错误过虑
            if (firstLogicValue>=15):
                return CT_ERROR
    
            #连牌判断
            for i in range(analyseResult.SignedCount):
                cardData=analyseResult.SignedCardData[i]
                if (firstLogicValue!=(self.GetCardLogicValue(cardData)+i)):
                    return CT_ERROR
    
            return CT_SINGLE_LINE
        return CT_ERROR    
    
    #获取数值
    def GetCardValue(self, CardData):
        return CardData & MASK_VALUE
    
    #获取花色
    def GetCardColor(self, CardData):
        return CardData & MASK_COLOR
    
    #获取炸弹数
    def GetBombCount(self, CardData):
        count = 0
        analyseResult = self.AnalyseCardData(CardData)
        count += analyseResult.FourCount
        
        for i in analyseResult.DoubleCount:
            value = self.GetCardLogicValue(analyseResult.DoubleCardData[i])
            if (value==0x4E or value==0x4F):
                count += 1
        return count
            
    
    ######### 控制函数
    #混乱扑克
    def RandCardList(self, CardBuffer):
        card_copy = copy(CardBuffer)
        return shuffle(card_copy)
    
    #得到好牌
    def GetGoodCardData(self, GoodCardData):
        pass
    
    #删除好牌
    def RemoveGoodCardData(self, GoodcardData, GoodCardCount, CardData, CardCount):
        pass
    
    #排列扑克
    def SortCardList(self, CardData, SortType):
        cardCount = len(CardData)
        if cardCount == 0: return
        sortValue = []
        for i in range(cardCount):
            sortValue[i] = self.GetCardLogicValue(CardData[i])
        
        sorted = False
        threeCount,last = cardCount-1
        while not sorted:
            sorted = True
            for i in range(last):
                if sortValue[i]<sortValue[i+1] or (sortValue[i]==sortValue[i+1] and CardData[i]<CardData[i+1]):
                    #交换位置
                    threeCount = CardData[i]
                    CardData[i] = CardData[i+1]
                    CardData[i+1] = threeCount
                    threeCount = sortValue[i]
                    sortValue[i] = sortValue[i+1]
                    sortValue[i+1] = threeCount
                    sorted = False
            last -= 1        
        #数目排序
        if SortType == ST_COUNT:
            index = 0
            analyseResult = self.AnalyseCardData(CardData)
            #拷贝四牌
            index2 = index + analyseResult.FourCount*4
            CardData[index:index2] = analyseResult.FourCardData
            #拷贝三牌
            index = index2
            index2 = index + analyseResult.ThreeCount*3
            CardData[index:index2] = analyseResult.ThreeCount
            #拷贝对牌
            index = index2
            index2 = index + analyseResult.DoubleCount*2
            CardData[index:index2] = analyseResult.DoubleCardData
            #拷贝单牌
            index = index2
            index2 = index + analyseResult.SignedCount
            CardData[index:index2] = analyseResult.SignedCardData
    
    #删除扑克
    def RemoveCard(self, RemoveCard, CardData):
        for card in RemoveCard:
            CardData.remove(card)
            
    
    #随机扑克
    def GetRandomCard(self): 
        return choice(FullCardData)
    
    ######### 逻辑函数
    #有效判断
    def IsValidCard(self, CardData):
        color = self.GetCardColor(CardData)
        value = self.GetCardValue(CardData)
        if (value == 0x4E or value == 0x4F):
            return True
        if (color <= 0x30 and value >= 0x01 and value <= 0x0D):
            return True
        return False

    #逻辑数值
    def GetCardLogicValue(self, CardData):
        color = self.GetCardColor(CardData)
        value = self.GetCardValue(CardData) 
        assert value>0 and value<=(MASK_VALUE&0x4f)
        #转换数值
        if (color==0x40):
            return value+2
        if (value <= 2):
            return value + 13
        else:
            return value
    
    #对比扑克
    def CompareCard(self, FirstCard, NextCard):
        FirstCount = len(FirstCard)
        NextCount = len(NextCard)
        
        #获取类型
        NextType = self.GetCardType(NextCard,NextCount)
        FirstType = self.GetCardType(FirstCard,FirstCount)
    
        #类型判断
        if (NextType==CT_ERROR):
            return False
        if (NextType==CT_MISSILE_CARD):
            return True
        if (FirstType==CT_MISSILE_CARD):
            return False 
    
        #炸弹判断
        if ((FirstType!=CT_BOMB_CARD)and(NextType==CT_BOMB_CARD)):
            return True
        if ((FirstType==CT_BOMB_CARD)and(NextType!=CT_BOMB_CARD)):
            return False
    
        #规则判断
        if ((FirstType!=NextType) or (FirstCount!=NextCount)):
            return False
    
        #开始对比
        if NextType == CT_SINGLE or NextType == CT_DOUBLE or NextType == CT_THREE or NextType == CT_SINGLE_LINE or NextType == CT_DOUBLE_LINE or NextType == CT_THREE_LINE or NextType == CT_BOMB_CARD: 
            #获取数值
            NextLogicValue=self.GetCardLogicValue(NextCard[0])
            FirstLogicValue=self.GetCardLogicValue(FirstCard[0])

            #对比扑克
            return NextLogicValue>FirstLogicValue
        elif NextType == CT_THREE_LINE_TAKE_ONE or NextType == CT_THREE_LINE_TAKE_TWO:
            #分析扑克
            NextResult = self.AnalyseCardData(NextCard)
            FirstResult = self.AnalyseCardData(FirstCard)
    
            #获取数值
            NextLogicValue=self.GetCardLogicValue(NextResult.ThreeCardData[0])
            FirstLogicValue=self.GetCardLogicValue(FirstResult.ThreeCardData[0])

            #对比扑克
            return NextLogicValue>FirstLogicValue
        elif NextType == CT_FOUR_LINE_TAKE_ONE or NextType == CT_FOUR_LINE_TAKE_TWO:
            NextResult = self.AnalyseCardData(NextCard)
            FirstResult = self.AnalyseCardData(FirstCard)
    
            #获取数值
            NextLogicValue=self.GetCardLogicValue(NextResult.ThreeCardData[0])
            FirstLogicValue=self.GetCardLogicValue(FirstResult.ThreeCardData[0])

            #对比扑克
            return NextLogicValue>FirstLogicValue
    
        return False
        
    
    ######### 内部函数
    #分析扑克
    def AnalyseCardData(self, CardData):
        analyseResult = AnalyseResult()
        cardCount = len(CardData)
        for i in range(cardCount):
            sameCount = 1
            logicValue = self.GetCardLogicValue(CardData[i])
            if logicValue <= 0:
                analyseResult.Success = False
                return analyseResult
            
            #搜索同牌
            for j in range(i+1, cardCount, 1):
                if (self.GetCardLogicValue(CardData[j] != logicValue)):
                    sameCount +=  1
                    
            if sameCount == 1:      #单张
                analyseResult.SignedCount += 1
                index = analyseResult.SignedCount
                analyseResult.SignedCardData[index*sameCount] = CardData[i]
                break
            elif sameCount == 2:    #两张    
                analyseResult.DoubleCount += 1
                index = analyseResult.DoubleCount
                analyseResult.DoubleCardData[index*sameCount]=CardData[i]
                analyseResult.DoubleCardData[index*sameCount+1]=CardData[i+1]
                break
            elif sameCount == 3:    #三张    
                analyseResult.ThreeCount += 1
                index = analyseResult.ThreeCount
                analyseResult.ThreeCardData[index*sameCount]=CardData[i]
                analyseResult.ThreeCardData[index*sameCount+1]=CardData[i+1]
                analyseResult.ThreeCardData[index*sameCount+2]=CardData[i+2]
                break
            elif sameCount == 4:    #四张
                analyseResult.FourCount += 1
                index = analyseResult.FourCount
                analyseResult.FourCardData[index*sameCount]=CardData[i]
                analyseResult.FourCardData[index*sameCount+1]=CardData[i+1]
                analyseResult.FourCardData[index*sameCount+2]=CardData[i+2]
                analyseResult.FourCardData[index*sameCount+3]=CardData[i+3]                
                
            i += sameCount-1
        analyseResult.Success = True
        return analyseResult
    
    ################## AI函数 ##################
    ######### 设置函数
    #设置扑克
    def SetUserCard(self, ChairID, CardData):
        self.AllCardData[ChairID] = CardData
        self.SortCardList(self.AllCardData[ChairID], ST_ORDER)
    
    #设置底牌
    def SetBackCard(self, ChairID, BackCardData):
        self.AllCardData[ChairID].extend(BackCardData)
        self.SortCardList(self.AllCardData[ChairID], ST_ORDER)
    
    #设置庄家
    def SetBanker(self, BankerUser):
        self.BankerUser = BankerUser
        self.BankerOutCardCount = 0
    
    #叫牌扑克
    def SetLandScoreCardData(self, CardData):
        assert len(CardData) == MAX_COUNT
        self.LandScoreCardData = CardData
        self.SortCardList(self.LandScoreCardData, ST_ORDER)
    
    #删除扑克
    def RemoveUserCardData(self,ChairID, RemoveCardData):
        self.RemoveCard(RemoveCardData, self.AllCardData[ChairID])
    
    #########
    ######### 辅助函数
    #组合算法
    def Combination(self):
        pass
    
    #排列算法
    def Permutation(self):
        pass
    
    #分析炸弹
    def GetAllBomCard(self, HandCardData):
        HandCardCount = len(HandCardData) 
        if HandCardCount<2: return
        
        cardData = HandCardData
        bomCardData = []
        self.SortCardList(cardData, ST_ORDER)
        bomCardCount = 0
        #双王炸弹
        if 0x4F==cardData[0] and 0x4E==cardData[1]:
            bomCardData[bomCardCount] = cardData[0]
            bomCardCount += 1
            bomCardData[bomCardCount] = cardData[1]
        
        #扑克分析
        for i in range(HandCardCount):
            sameCount = 1
            value = self.GetCardLogicValue(cardData[i])
            
            for j in range(i+1, HandCardCount, 1):
                if (self.GetCardLogicValue(cardData[j] != value)): break
                sameCount +=  1
            if sameCount==4:
                bomCardData.extend(cardData[i,i+4])
            i += sameCount-1
                
    #分析顺子
    def GetAllLineCard(self, HandCardData):
        HandCardCount = len(HandCardData) 
        if HandCardCount<5: return
        
        cardData = HandCardData
        lineCardData = []
        self.SortCardList(cardData, ST_ORDER)
        
        firstCard = 0
        #去除2和王
        for i in range(HandCardCount):
            if self.GetCardLogicValue(cardData[i]<15):
                firstCard = i
                break
        SingleLineCard = []
        SingleLineCount = 0
        LeftCardCount = HandCardCount
        FindSingleLine = True
        
        while LeftCardCount>=5 and FindSingleLine:
            SingleLineCount = 1
            FindSingleLine = False
            LastCard = cardData[firstCard]
                
            
        lineCardCount = 0
            
    #分析三条
    def GetAllThreeCard(self):
        pass
    
    #分析对子
    def GetAllDoubleCard(self):
        pass
    
    #分析单牌
    def GetAllSingleCard(self):
        pass
    
    #出牌测试
    def _TestOutAllCard(self):
        pass
    
    #出牌测试
    def TestOutAllCard(self):
        pass
    
    #四带牌型
    def AnalyseFourCardType(self):
        pass
    
    #最大判断
    def IsLargestCard(self):
        pass
    
    #是否能出
    def VerifyOutCard(self):
        pass
    
    
    ######### 主要函数
    #分析牌型（后出牌调用）
    def AnalyseOutCardType(self):
        pass
    
    #分析牌牌（先出牌调用）
    def AnalyseOutCardType2(self):
        pass
    
    ######### 出牌函数
    #单牌个数
    def AnalyseSinleCardCount(self):
        pass
    
    #地主出牌（先出牌）
    def BankerOutCard(self):
        pass
    
    #地主出牌（后出牌）
    def BankerOutCard2(self):
        pass
    
    #地主上家（先出牌）
    def UpsideOfBankerOutCard(self):
        pass
    
    #地主上家（后出牌）
    def UpsideOfBankerOutCard2(self):
        pass
    
    #地主下家（先出牌）
    def UndersideOfBankerOutCard(self):
        pass
    
    #地主下家（后出牌）
    def UndersideOfBankerOutCard2(self):
        pass
    
    #出牌搜索
    def SearchOutCard(self):
        pass
    
    ######### 叫分函数
    #叫分判断
    def LandScore(self):
        pass

